package com.wpen.unit.web.utils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import com.wpen.unit.commun.BaseResponse;
import com.wpen.unit.utils.JsonUtil;
import com.wpen.unit.utils.SpringUtil;
import com.wpen.unit.web.WebVariables;

import lombok.extern.slf4j.Slf4j;

/**
 * http 调用
 *
 * @author Wang Peng
 * @date 2022年12月9日
 * 
 */
@Slf4j
public class HttpService<T> {

    public T proxyPostHttp(String servicePath, String uri, Map<String, List<String>> header, Object body,
            Class<T> clazz) {
        return proxyPostHttp(servicePath, uri, header, body, clazz, false);
    }

    @SuppressWarnings("unchecked")
    public T proxyPostHttp(String servicePath, String uri, Map<String, List<String>> header, Object body,
            Class<T> clazz, boolean http200CheckEx) {
        if (log.isDebugEnabled()) {
            log.debug("====Proxy URL>>" + servicePath + uri);
            log.debug("====Proxy Header>>" + JsonUtil.toJson(header));
            log.debug("====Proxy Body>>"
                    + (body == null ? "" : JsonUtil.toJson(body).replaceAll("\r\n", "").replaceAll("\n", "")));
        }
        HttpHeaders headers = new HttpHeaders();
        List<String> cookies_mj = new ArrayList<>();
        headers.put(HttpHeaders.COOKIE, cookies_mj);
        if (header != null) {
            for (Map.Entry<String, List<String>> entry : header.entrySet()) {
                headers.put(entry.getKey(), entry.getValue());
            }
        }
        HttpEntity<Object> requestEntity = new HttpEntity<>(body, headers);
        RestTemplate restTemplate = SpringUtil.getBean(RestTemplate.class);
        ResponseEntity<Resource> responseEntity = restTemplate.postForEntity(servicePath + uri, requestEntity,
                Resource.class);
        Resource object = responseEntity.getBody();
        String responseData = dumpStream(object);
        if (log.isDebugEnabled()) {
            log.debug("===Proxy Result>>"
                    + (responseData == null ? "" : responseData.replaceAll("\r\n", "").replaceAll("\n", "")));
        }
        T t = null;
        if (HttpStatus.OK == responseEntity.getStatusCode()) {
            t = (T) JsonUtil.toObject(responseData, clazz);
            if (http200CheckEx) {
                if (t instanceof BaseResponse) {
                    BaseResponse response = (BaseResponse) t;
                    if (!WebVariables.RESPONSE_SUCC_CODE.equals(response.getCode())) {
                        throw new RuntimeException(response.getMsg());
                    }
                }
            }
        } else {
            throw new RuntimeException(responseData);
        }
        return t;
    }

    public T proxyGetHttp(String servicePath, String uri, Map<String, List<String>> header, Map<String, Object> params,
            Class<T> clazz) {
        return proxyGetHttp(servicePath, uri, header, params, clazz, true);
    }

    @SuppressWarnings("unchecked")
    public T proxyGetHttp(String servicePath, String uri, Map<String, List<String>> header, Map<String, Object> params,
            Class<T> clazz, boolean http200CheckEx) {
        if (log.isDebugEnabled()) {
            log.debug("====Proxy URL>>" + servicePath + uri);
            log.debug("====Proxy Header>>" + JsonUtil.toJson(header));
            log.debug("====Proxy Body>>"
                    + (params == null ? "" : JsonUtil.toJson(params).replaceAll("\r\n", "").replaceAll("\n", "")));
        }
        HttpHeaders headers = new HttpHeaders();
        List<String> cookies_mj = new ArrayList<>();
        headers.put(HttpHeaders.COOKIE, cookies_mj);
        if (header != null) {
            for (Map.Entry<String, List<String>> entry : header.entrySet()) {
                headers.put(entry.getKey(), entry.getValue());
            }
        }
        ResponseEntity<Resource> responseEntity = null;
        HttpEntity<Map<String, Object>> requestService = new HttpEntity<>(params, headers);
        StringBuffer sBuffer = new StringBuffer();
        String joinParams = "";
        if (params != null && !params.isEmpty()) {
            sBuffer.append("?");
            Set<Map.Entry<String, Object>> set = params.entrySet();
            for (Entry<String, Object> entry : set) {
                sBuffer.append(entry.getKey() + "=" + entry.getValue() + "&");
            }
            joinParams = sBuffer.toString().substring(0, sBuffer.length() - 1);
        }
        RestTemplate restTemplate = SpringUtil.getBean(RestTemplate.class);
        responseEntity = restTemplate.exchange(servicePath + uri + joinParams, HttpMethod.GET, requestService,
                Resource.class);
        Resource object = responseEntity.getBody();
        String responseData = dumpStream(object);
        if (log.isDebugEnabled()) {
            log.debug("===Proxy Result>>"
                    + (responseData == null ? "" : responseData.replaceAll("\r\n", "").replaceAll("\n", "")));
        }
        T t = null;
        if (HttpStatus.OK == responseEntity.getStatusCode()) {
            t = (T) JsonUtil.toObject(responseData, clazz);
            if (http200CheckEx) {
                if (t instanceof BaseResponse) {
                    BaseResponse response = (BaseResponse) t;
                    if (!WebVariables.RESPONSE_SUCC_CODE.equals(response.getCode())) {
                        throw new RuntimeException(response.getMsg());
                    }
                }
            }
        } else {
            throw new RuntimeException(responseData);
        }
        return t;
    }

    private String dumpStream(Resource resource) {
        InputStream is = null;
        try {
            // 1、获取文件资源
            is = resource.getInputStream();
            // 2、读取资源
            byte[] descBytes = new byte[is.available()];// java.io.InputStream.available返回此输入流方法的下一个调用方可以不受阻塞地从此输入流读取（或跳过）的字节数
            is.read(descBytes);
            return new String(descBytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 3、关闭资源
                is.close();
            } catch (Exception e) {
            }
        }
        return null;
    }
}
